from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
import uvicorn
import logging
import traceback

from app.core.config.settings import settings
from app.core.database.connection import init_database
from app.api.v1.router import api_router
from app.shared.schemas.response import error_response
from app.shared.constants.status_codes import BusinessCode

# 配置日志
logging.basicConfig(
    level=getattr(logging, settings.LOG_LEVEL),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

logger = logging.getLogger(__name__)

# 创建FastAPI应用实例
app = FastAPI(
    title="美申智控系统API",
    description="便携式厕所智能管理系统后端服务",
    version="1.0.0",
    docs_url="/docs" if settings.DEBUG else None,
    redoc_url="/redoc" if settings.DEBUG else None,
    openapi_url="/openapi.json" if settings.DEBUG else None,
)

# 添加中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.ALLOWED_HOSTS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.add_middleware(GZipMiddleware, minimum_size=1000)

# 挂载静态文件（如果存在）
try:
    app.mount("/static", StaticFiles(directory="static"), name="static")
except:
    logger.warning("⚠️  静态文件目录不存在，跳过挂载")

# 注册路由
app.include_router(api_router)

# 全局异常处理器
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
    """HTTP异常处理"""
    logger.warning(f"HTTP异常: {exc.status_code} - {exc.detail}")
    
    return JSONResponse(
        status_code=exc.status_code,
        content=error_response(
            message=exc.detail,
            code=exc.status_code
        )
    )


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    """请求验证异常处理"""
    logger.warning(f"请求验证失败: {exc}")
    
    errors = []
    for error in exc.errors():
        field_path = " -> ".join([str(loc) for loc in error["loc"]])
        errors.append({
            "field": field_path,
            "message": error["msg"],
            "value": error.get("input")
        })
    
    return JSONResponse(
        status_code=422,
        content=error_response(
            message="请求参数验证失败",
            code=BusinessCode.PARAM_ERROR,
            errors=errors
        )
    )


@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
    """通用异常处理"""
    logger.error(f"未处理异常: {exc}")
    logger.error(traceback.format_exc())
    
    return JSONResponse(
        status_code=500,
        content=error_response(
            message="服务器内部错误，请联系管理员" if not settings.DEBUG else str(exc),
            code=BusinessCode.OPERATION_FAILED
        )
    )


@app.on_event("startup")
async def startup_event():
    """应用启动时初始化"""
    try:
        logger.info("🚀 美申智控系统正在启动...")
        
        # 初始化数据库连接
        await init_database()
        
        # 初始化MQTT连接
        try:
            from app.core.mqtt.client import mqtt_manager
            from app.services.device_mqtt_service import device_mqtt_service
            
            await mqtt_manager.connect()
            await device_mqtt_service.setup_handlers()
            
            logger.info("✅ MQTT服务初始化完成")
        except Exception as e:
            logger.error(f"❌ MQTT服务初始化失败: {e}")
            # MQTT失败不阻止应用启动
        
        logger.info("🎉 美申智控系统启动完成")
        logger.info(f"📋 服务信息:")
        logger.info(f"   - 版本: 1.0.0")
        logger.info(f"   - 调试模式: {settings.DEBUG}")
        logger.info(f"   - API文档: http://localhost:{settings.PORT}/docs" if settings.DEBUG else "   - API文档: 已禁用")
        
    except Exception as e:
        logger.error(f"💥 应用启动失败: {e}")
        raise


@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭时清理资源"""
    try:
        logger.info("🔄 美申智控系统正在关闭...")
        
        # 关闭MQTT连接
        try:
            from app.core.mqtt.client import mqtt_manager
            await mqtt_manager.disconnect()
            logger.info("✅ MQTT连接已关闭")
        except Exception as e:
            logger.error(f"❌ 关闭MQTT连接失败: {e}")
        
        logger.info("✋ 美申智控系统已关闭")
        
    except Exception as e:
        logger.error(f"💥 应用关闭失败: {e}")


@app.get("/")
async def root():
    """根路径"""
    return {
        "message": "美申智控系统API服务",
        "version": "1.0.0",
        "status": "running",
        "docs": "/docs" if settings.DEBUG else None
    }


@app.get("/health")
async def health_check():
    """健康检查端点"""
    try:
        # 检查数据库连接
        from app.core.database.connection import SessionLocal
        db = SessionLocal()
        db.execute("SELECT 1")
        db.close()
        db_status = "healthy"
    except Exception as e:
        logger.error(f"数据库健康检查失败: {e}")
        db_status = "unhealthy"
    
    # 检查MQTT连接
    try:
        from app.core.mqtt.client import mqtt_manager
        mqtt_status = "healthy" if mqtt_manager.is_connected else "disconnected"
    except:
        mqtt_status = "unavailable"
    
    return {
        "status": "healthy" if db_status == "healthy" else "degraded",
        "timestamp": "2024-01-01T12:00:00Z",  # 实际应用中应该使用真实时间戳
        "services": {
            "database": db_status,
            "mqtt": mqtt_status
        },
        "version": "1.0.0"
    }


if __name__ == "__main__":
    uvicorn.run(
        "app.main:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=settings.DEBUG,
        log_level="info"
    )